package org.jadelyre.core.worker;

import org.jadelyre.core.Channel;
import org.jadelyre.core.JadeLyre;
import org.jadelyre.core.JadeLyreConfig;
import org.jadelyre.core.ThreadPool;
import org.jadelyre.core.codec.Packet;
import org.jadelyre.core.exception.JadeLyreException;
import org.jadelyre.core.task.EntryQueue;
import org.jadelyre.jade.JadeCloseWorker;
import org.jadelyre.jade.JadeServer;
import org.jadelyre.lyre.LyreCloseWorker;

import java.nio.ByteBuffer;
import java.util.concurrent.ThreadPoolExecutor;

public class WorkerFactory {


    private ThreadPoolExecutor decodeThreadPool;
    private ThreadPoolExecutor handleThreadPool;
    private ThreadPoolExecutor writeThreadPool;
    private ThreadPoolExecutor closeThreadPool;
    private ThreadPoolExecutor scheduledThreadPool;

    public Worker<ByteBuffer> getDecodeWorker(Channel channel, EntryQueue<ByteBuffer> entryQueue) {
        DecodeWorker decodeWorker = new DecodeWorker(channel, decodeThreadPool, entryQueue);
        return decodeWorker;
    }

    public Worker<Packet> getHandleWorker(Channel channel, EntryQueue<Packet> entryQueue) {
        HandleWorker handleWorker = new HandleWorker(channel, handleThreadPool, entryQueue);
        return handleWorker;
    }

    public Worker<Packet> getWriteWorker(Channel channel, EntryQueue<Packet> entryQueue) {
        SendWorker writeWorker = new SendWorker(channel, writeThreadPool, entryQueue);
        return writeWorker;
    }

    public Worker<Channel> getCloseWorker(JadeLyre jadeLyre, EntryQueue<Channel> entryQueue) {
        if (jadeLyre instanceof JadeServer) {
            return new JadeCloseWorker(closeThreadPool, entryQueue);
        } else {
            return new LyreCloseWorker(closeThreadPool, entryQueue);
        }
    }

    public Worker<Schedule> getScheduledWorker(JadeLyre jadeLyre, EntryQueue<Schedule> entryQueue) {
        ScheduledWorker scheduledWorker = new ScheduledWorker(scheduledThreadPool, entryQueue);
        return scheduledWorker;
    }


    public WorkerFactory(JadeLyreConfig jadeLyreConfig){
        boolean flexible = jadeLyreConfig.isFlexible();
        if (flexible){
            int decodePoolSize = jadeLyreConfig.getDecodePoolSize();
            int handlePoolSize = jadeLyreConfig.getHandlePoolSize();
            int writePoolSize = jadeLyreConfig.getWritePoolSize();
            int closePoolSize = jadeLyreConfig.getClosePoolSize();
            int scheduledPoolSize = jadeLyreConfig.getScheduledPoolSize();
            decodeThreadPool = ThreadPool.createThreadPool(decodePoolSize);
            handleThreadPool = ThreadPool.createThreadPool(handlePoolSize);
            writeThreadPool = ThreadPool.createThreadPool(writePoolSize);
            closeThreadPool = ThreadPool.createThreadPool(closePoolSize);
            scheduledThreadPool = ThreadPool.createScheduledThreadPool(scheduledPoolSize);
        }else {
            int sharedPoolSize = jadeLyreConfig.getSharedPoolSize();
            int scheduledPoolSize = jadeLyreConfig.getScheduledPoolSize();
            ThreadPoolExecutor sharedPool = ThreadPool.createThreadPool(sharedPoolSize);
            ThreadPoolExecutor scheduledPool = ThreadPool.createScheduledThreadPool(scheduledPoolSize);
            decodeThreadPool = sharedPool;
            handleThreadPool = sharedPool;
            writeThreadPool = sharedPool;
            closeThreadPool = sharedPool;
            scheduledThreadPool = scheduledPool;
        }
    }

}
